Problem s strlower()
Otázka od: Vymazal Milan
12. 11. 2002 15:49
Zdravim
mam takovej zvlastni problem, asi to bude moji blbosti ale nevim si s
necim rady. Mam v programu kousek kodu ktere ze seznamu souboru
provede trideni. pokud ma soubor koncovku .sa tak ho hodi do satemp a
pokud ne tak do recordtempu. Jenze proto abych overil tu priponu potrebuji
ten zaznam prevest na mala pismena. to delam v promene radek.
var
satemp,recordtemp:TStringList;
begin
SaTemp:=TStringList.create;
RecordTemp:=TStringLIst.create;
FindFile.Directory:=datapath;
FindFile.Filter:='*.*';
FindFile.Recurse:=true;
FindFile.Execute;
for i:=0 to FindFile.Files.Count-1 do
begin
radek:=(findfile.files[i]);
d('1'+findfile.files[i]);
// v teto casti mi to vypise findfiles.files[i] s nezmenenejma
pismenama to je ok.
strlower(pchar(radek));
d('2'+findfile.files[i]); << tady to vypise vsechno maly ??
// tady uz jsou vsechna pismena mala ? ale proc vzdyt uz s
findfile.files[i] nepracuji ? Nepotrebuji aby to bylo male
potrebuji aby to bylo s originalni velikosti
if extractfileext(radek)='.sa' then
Satemp.Add(findfile.files[i])
else RecordTemp.Add(findfile.files[i]);
end;
Odpovedá: ing. Jan Fiala
12. 11. 2002 13:42
protoze Radek je PChar a to je jen ukazatel na retezec. Takze pokud
pracujes s Radek, provadis to vlastne i s tim puvodnim retezcem.
--
ing. Jan Fiala
mailto:jan.fiala@iol.cz
12.11.2002 Vymazal Milan:
> Zdravim
> mam takovej zvlastni problem, asi to bude moji blbosti ale nevim si s
> necim rady. Mam v programu kousek kodu ktere ze seznamu souboru
> provede trideni. pokud ma soubor koncovku .sa tak ho hodi do satemp a
> pokud ne tak do recordtempu. Jenze proto abych overil tu priponu potrebuji
> ten zaznam prevest na mala pismena. to delam v promene radek.
> var
> satemp,recordtemp:TStringList;
> begin
> SaTemp:=TStringList.create;
> RecordTemp:=TStringLIst.create;
> FindFile.Directory:=datapath;
> FindFile.Filter:='*.*';
> FindFile.Recurse:=true;
> FindFile.Execute;
> for i:=0 to FindFile.Files.Count-1 do
> begin
> radek:=(findfile.files[i]);
> d('1'+findfile.files[i]);
> // v teto casti mi to vypise findfiles.files[i] s nezmenenejma
> pismenama to je ok.
> strlower(pchar(radek));
> d('2'+findfile.files[i]); << tady to vypise vsechno maly ??
> // tady uz jsou vsechna pismena mala ? ale proc vzdyt uz s
> findfile.files[i] nepracuji ? Nepotrebuji aby to bylo male
> potrebuji aby to bylo s originalni velikosti
> if extractfileext(radek)='.sa' then
> Satemp.Add(findfile.files[i])
> else RecordTemp.Add(findfile.files[i]);
> end;
Odpovedá: Ondrej Kelle
12. 11. 2002 14:15
> Mam v programu kousek kodu ktere ze seznamu souboru
> provede trideni. pokud ma soubor koncovku .sa tak ho hodi do satemp a
> pokud ne tak do recordtempu. Jenze proto abych overil tu
> priponu potrebuji
> ten zaznam prevest na mala pismena. to delam v promene radek.
Neviem, akeho typu je FindFile, ale predpokladam, ze TOpenDialog. V tom
pripade si narazil na reference counting dlhych stringov.
>
> for i:=0 to FindFile.Files.Count-1 do
> begin
> radek:=(findfile.files[i]);
radek ukazuje na ten isty retazec v pameti ako findfile.files[I], iba
refcount sa zvysil.
> d('1'+findfile.files[i]);
>
> // v teto casti mi to vypise findfiles.files[i] s nezmenenejma
> pismenama to je ok.
>
> strlower(pchar(radek));
> d('2'+findfile.files[i]); << tady to vypise vsechno maly ??
See above
>
> // tady uz jsou vsechna pismena mala ? ale proc vzdyt uz s
> findfile.files[i] nepracuji ? Nepotrebuji aby to bylo male
> potrebuji aby to bylo s originalni velikosti
> if extractfileext(radek)='.sa' then
> Satemp.Add(findfile.files[i])
> else RecordTemp.Add(findfile.files[i]);
> end;
Najjednoduchsie bude podla mna vyhodit to volanie strlower a tu podmienku
napisat takto:
if SameText(ExtractFileExt(radek), '.sa') then
kedze pre '.sa' nepotrebujes porovnavat podla locale. Inak by sa hodilo
AnsiCompareText.
HTH
TOndrej
Odpovedá: Dalibor Toman
12. 11. 2002 15:41
>
> Neviem, akeho typu je FindFile, ale predpokladam, ze TOpenDialog. V
tom
> pripade si narazil na reference counting dlhych stringov.
>
> >
> > for i:=0 to FindFile.Files.Count-1 do
> > begin
> > radek:=(findfile.files[i]);
>
> radek ukazuje na ten isty retazec v pameti ako findfile.files[I],
iba
> refcount sa zvysil.
rekl bych, ze ref count se nezmenil. Pokud je radek typu Pchar nema
smysl zvysovat
counter referenci, protoze kompilator stejne neni schopen na PChar
generovat kod pro automaticke uvolneni atd.
to prirazeni je ekvivalentni:
pointervar := @stringvar[1]
D. Toman
Odpovedá: Ondrej Kelle
12. 11. 2002 17:36
> rekl bych, ze ref count se nezmenil. Pokud je radek typu Pchar nema
> smysl zvysovat counter referenci, protoze kompilator stejne neni
> schopen na PChar generovat kod pro automaticke uvolneni atd.
Mas pravdu v tom, ze z povodneho prispevku nebolo jasne, akeho typu je
premenna radek.
Ja som automaticky predpokladal, ze je typu string, kvoli tomu typecastu na
PChar:
>> strlower(pchar(radek));
Kedze dnes som uz k celkovej entropii prispel dost, tu je jednoduchy
skompilovatelny priklad, ktory demonstruje to, co som mal na mysli:
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
S: string;
begin
with OpenDialog1 do
if Execute then
for I := 0 to Files.Count - 1 do
begin
OutputDebugString(PChar(Files[I])); // povodny file name (mixed
case)
S := Files[I];
OutputDebugString(PChar(Format('Files[%d]: $%.8x, S: $%.8x', [I,
Integer(Pointer(Files[I])),
Integer(Pointer(S))]))); // rovnake adresy
StrLower(PChar(S));
OutputDebugString(PChar(Files[I])); // zmeneny file name (lower
case)
end;
end;
kde OpenDialog1 je typu TOpenDialog.
To, ze pri priradeni do premennej typu string sa zvysi refcount, sa da
zistit nejako takto:
// copied from System implementation
type
PStrRec = ^StrRec;
StrRec = packed record
refCnt: Longint;
length: Longint;
end;
function StrRefCount(S: PChar): Integer;
var
P: PStrRec;
begin
P := PStrRec(Integer(S) - SizeOf(StrRec));
Result := P^.refCnt;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
P: PChar;
S: string;
begin
with OpenDialog1 do
if Execute then
begin
P := PChar(Files[0]);
OutputDebugString(PChar(Format('P: $%.8x, refCnt: %d',
[Integer(P), StrRefCount(P)])));
// P: $00C22024, refCnt: 3
// assignment by reference, increments refcount
S := Files[0];
OutputDebugString(PChar(Format('P: $%.8x, refCnt: %d, S: $%.8x,
refCnt: %d',
[Integer(P), StrRefCount(P), Integer(PChar(S)),
StrRefCount(PChar(S))])));
// P: $00C22024, refCnt: 4, S: $00C22024, refCnt: 4
// copy on demand: creates new string
Delete(S, 1, 1);
OutputDebugString(PChar(Format('P: $%.8x, refCnt: %d, S: $%.8x,
refCnt: %d',
[Integer(P), StrRefCount(P), Integer(PChar(S)),
StrRefCount(PChar(S))])));
// P: $00C22024, refCnt: 3, S: $00C30070, refCnt: 1
end;
end;
HTH
TOndrej
Odpovedá: Vymazal Milan
12. 11. 2002 14:57
Cau
iJF> protoze Radek je PChar a to je jen ukazatel na retezec. Takze pokud
iJF> pracujes s Radek, provadis to vlastne i s tim puvodnim retezcem.
aha. no nahradil jsem to lowercase. Ja jsem to rikal ze je to mo
debilitou.
--
Best regards,
Vymazal mailto:vymazal.milan@seznam.cz
Odpovedá: Vymazal Milan
12. 11. 2002 14:57
Cau Ondrej,
Tuesday, November 12, 2002, 12:44:38 PM, you wrote:
>> Mam v programu kousek kodu ktere ze seznamu souboru
>> provede trideni. pokud ma soubor koncovku .sa tak ho hodi do satemp a
>> pokud ne tak do recordtempu. Jenze proto abych overil tu
>> priponu potrebuji
>> ten zaznam prevest na mala pismena. to delam v promene radek.
> Neviem, akeho typu je FindFile, ale predpokladam, ze TOpenDialog. V tom
> pripade si narazil na reference counting dlhych stringov.
ne ne FindFile je TStringList; Ale to je jedno to neres dal jsem tam
lowercase a vsechno je ready
>>
>> for i:=0 to FindFile.Files.Count-1 do
>> begin
>> radek:=(findfile.files[i]);
> radek ukazuje na ten isty retazec v pameti ako findfile.files[I], iba
> refcount sa zvysil.
>> d('1'+findfile.files[i]);
>>
>> // v teto casti mi to vypise findfiles.files[i] s nezmenenejma
>> pismenama to je ok.
>>
>> strlower(pchar(radek));
>> d('2'+findfile.files[i]); << tady to vypise vsechno maly ??
> See above
>>
>> // tady uz jsou vsechna pismena mala ? ale proc vzdyt uz s
>> findfile.files[i] nepracuji ? Nepotrebuji aby to bylo male
>> potrebuji aby to bylo s originalni velikosti
>> if extractfileext(radek)='.sa' then
>> Satemp.Add(findfile.files[i])
>> else RecordTemp.Add(findfile.files[i]);
>> end;
> Najjednoduchsie bude podla mna vyhodit to volanie strlower a tu podmienku
> napisat takto:
> if SameText(ExtractFileExt(radek), '.sa') then
> kedze pre '.sa' nepotrebujes porovnavat podla locale. Inak by sa hodilo
> AnsiCompareText.
> HTH
> TOndrej
S pozdravem
Milan Vymazal